package core

import (
	"context"
	"fmt"

	"github.com/astaxie/beego/logs"
	redis "github.com/go-redis/redis/v9"
)

const (
	// 订阅的市场所有key , 数据结构list
	wsSubMarketKey = "ws:exchange:sub:keys"
)

type RedisKeyRule struct {
	exchangeFmtKey     string              // xt:exchange:%s:%s
	exchangeNameFmtKey string              // binance
	lambda             func(string) string // strings.ToLower(ex)
}

func NewRedisKeyRule(exchangeFmtKey, exchangeNameFmtKey string, lambda func(string) string) *RedisKeyRule {
	return &RedisKeyRule{
		exchangeFmtKey:     exchangeFmtKey,
		exchangeNameFmtKey: exchangeNameFmtKey,
		lambda:             lambda,
	}
}

// get config from cache
type RedisOperate struct {
	Client *redis.Client
	key    RedisKeyRule
}

var (
	RedisOperator *RedisOperate
)

func NewRedisOperate(client *redis.Client, key RedisKeyRule) *RedisOperate {
	return &RedisOperate{Client: client, key: key}
}

func NewRedisOperateClient(client *redis.Client) *RedisOperate {
	return &RedisOperate{Client: client}

}

// Read the data in the cache
func (r RedisOperate) getData(data []string) (exchangeMarket, res []string) {
	res = data

	if r.key.exchangeFmtKey == "" {
		exchangeMarket = res
		return
	}

	for _, market := range data {

		marketKey := fmt.Sprintf(r.key.exchangeFmtKey, r.key.exchangeNameFmtKey, market)
		ex, err := r.Client.Get(context.TODO(), marketKey).Result()
		if err != nil {
			logs.Debug("[run-getData] load market config failed , err ", err, r.key)
			continue
		}

		exchangeMarket = append(exchangeMarket, r.key.lambda(ex))
	}
	return
}

// Acquire info
func (r RedisOperate) AcquireInfoFromCache(key string) (exchangeMarket, res []string) {

	if r.Client.Exists(context.TODO(), key).Val() == 0 {
		return
	}

	markets, err := r.Client.ZRange(context.TODO(), key, 0, -1).Result()
	if err != nil {
		logs.Debug("[run-AcquireInfoFromCache] load markets config failed , err ", err, key)
		return
	}

	exchangeMarket, res = r.getData(markets)
	return
}

// Acquire info
func (r RedisOperate) AcquireOwnerInfoFromCache(key string) (exchangeMarket, res []string) {

	if r.Client.Exists(context.TODO(), key).Val() == 0 {
		return
	}

	markets, err := r.Client.SMembers(context.TODO(), key).Result()
	if err != nil {
		logs.Debug("[run-AcquireInfoFromCache] load markets config failed , err ", err, key)
		return
	}

	exchangeMarket, res = r.getData(markets)
	return
}

// Basic information about the loader subscription
func (r RedisOperate) AcquireMarketInfoFromCache(redisKey string) (exchangeMarket, res []string) {

	return r.AcquireInfoFromCache(redisKey)
}

// Own subscription to the market information
func (r RedisOperate) AcquireOwnerMarketInfoFromCache(redisKey string) (exchangeMarket, res []string) {

	return r.AcquireOwnerInfoFromCache(redisKey)
}

// Write keys of exchange-sub-market to redis
func (r RedisOperate) AddSubExchangeKeys(key string) {
	r.Client.SAdd(context.TODO(), wsSubMarketKey, key)
}
